package top.swimmer.tokenizer.math;

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalField;
import java.time.temporal.TemporalUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Viterbi {
    static class Transfer {
        Status from;
        Status to;

        Transfer(Status from, Status to) {
            this.from = from;
            this.to = to;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Transfer transfer = (Transfer) o;

            if (from != transfer.from) return false;
            return to == transfer.to;
        }
    }

    static class Send {
        Status status;
        Activity activity;

        Send(Status status, Activity activity) {
            this.status = status;
            this.activity = activity;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Send send = (Send) o;

            if (status != send.status) return false;
            return activity == send.activity;
        }
    }

    enum Status {
        Rainy(10.6), Sunny(5.4), ddd(9);

        double rank;

        Status(double rank) {
            this.rank = rank;
        }
    }

    enum Activity {
        Walking, Shopping, Sleeping
    }

    public static void main(String[] args) {
//        Instant instant = Instant.now();
//        System.out.println(instant.toEpochMilli());
//        Duration duration = Duration.ofDays(30);
//        System.out.println(duration.get(TemporalUnit));
//        List<Integer> a = new ArrayList<Integer>() {{
//            add(123);
//            add(234);
//            add(456);
//            add(345);
//        }};
//
//        List<Integer> b = new ArrayList<Integer>() {{
//            add(123);
//            add(456);
//            add(678);
//        }};

//        Map<Integer, List<Integer>> map = new HashMap<>();
//        map.put(1, a);
//
//        List<Long> result = map.values().stream().flatMap(List::stream).map(Integer::longValue).collect(Collectors.toList());
//        System.out.println(result);

//        System.out.println(b.retainAll(a));
//        System.out.println(b);

        List<Status> statuses = Arrays.stream(Status.values()).collect(Collectors.toList());
        statuses.sort(new Comparator<Status>() {
            @Override
            public int compare(Status o1, Status o2) {
                if (o1.rank > o2.rank) {
                    return 1;
                } else if (o1.rank == o2.rank) {
                    return 0;
                }
                return -1;
            }
        });
//        System.out.println(statuses);
        List<Activity> activities = new ArrayList<Activity>() {{
            add(Activity.Walking);
            add(Activity.Shopping);
            add(Activity.Sleeping);
        }};
        Map<Transfer, Double> transfers = new HashMap<Transfer, Double>() {{
            put(new Transfer(Status.Rainy, Status.Rainy), 0.7);
            put(new Transfer(Status.Rainy, Status.Sunny), 0.3);
            put(new Transfer(Status.Sunny, Status.Rainy), 0.4);
            put(new Transfer(Status.Sunny, Status.Sunny), 0.6);
        }};
        Map<Send, Double> sends = new HashMap<Send, Double>() {{
            put(new Send(Status.Rainy, Activity.Walking), 0.1);
            put(new Send(Status.Rainy, Activity.Shopping), 0.4);
            put(new Send(Status.Rainy, Activity.Sleeping), 0.5);

            put(new Send(Status.Sunny, Activity.Walking), 0.6);
            put(new Send(Status.Sunny, Activity.Shopping), 0.3);
            put(new Send(Status.Sunny, Activity.Sleeping), 0.1);
        }};
    }

    static class Node {
        Status status;
        Status next;
        Double score;

    }

    public static List<Status> viterbi(List<Status> statuses, List<Activity> activities, Map<Transfer, Double> transfers, Map<Send, Double> sends) {
        for (Status status : statuses) {
            Node node = new Node();
            node.status = status;
            node.score = status.rank * sends.get(new Send(status, activities.get(0)));
        }
        return null;
    }
}
